#ifndef _PPM_H
#define _PPM_H

#include <stdint.h>
#include <avr/eeprom.h>
#include <string.h>
#include <avr/io.h>

#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "wiring.h"
#endif


enum RADIO_TYPE {RADIO_JR, RADIO_FUTABA};
enum SERVO_INDEX {SERVO_PITCH, SERVO_ROLL, SERVO_YAW};

struct servo_setting_t
{
    int8_t channel;
    int8_t trim;
    //uint8_t travel;
    uint16_t _max;
    uint16_t _min;
    uint8_t _speed;
    bool reverse;
    
    void init()
    {
    	channel = 0;
    	trim = 0;
    	_max = 2120;
    	_min = 920;
    	_speed = 100;
    	reverse = 0;
    } 
};

struct ppm_setting_t
{
    uint8_t mark;
    servo_setting_t servo_setting[3];
    RADIO_TYPE radio_type;
    bool mixing;
    
    void init()
    {
        mark = 'P';
    	radio_type = RADIO_JR;
        servo_setting[0].init();
                servo_setting[1].init();
                        servo_setting[2].init();
    	mixing = false;
    }
};

class PPM
{
public:
    static void init();
    //void update(int16_t* att);

    static inline void set_trim(uint8_t servo, int8_t trim)
    {
        setting.servo_setting[servo].trim = constrain(trim, TRIM_MIN, TRIM_MAX);
    }
    static inline int8_t get_trim(uint8_t servo)
    {
        return setting.servo_setting[servo].trim;
    }

    static inline void change_reverse(uint8_t servo)
    {
        setting.servo_setting[servo].reverse = !setting.servo_setting[servo].reverse;
    }
    static inline void set_reverse(uint8_t servo, bool rev)
    {
        setting.servo_setting[servo].reverse = rev;
    }
    static inline bool get_reverse(uint8_t servo)
    {
        return setting.servo_setting[servo].reverse;
    }

    static inline void set_channel(uint8_t servo, uint8_t channel)
    {
        setting.servo_setting[servo].channel = constrain(channel, 0, 8);
    }
    static inline uint8_t get_channel(uint8_t servo)
    {
        return setting.servo_setting[servo].channel;
    }

    static inline void set_speed(uint8_t servo, uint8_t _speed)
    {
        setting.servo_setting[servo]._speed = constrain(_speed, 0, 150);
    }
    static inline uint16_t get_speed(uint8_t servo)
    {
        return setting.servo_setting[servo]._speed;
    }

    static inline uint16_t get_min(uint8_t servo)
    {
        return setting.servo_setting[servo]._min;
    }

    static inline uint16_t get_max(uint8_t servo)
    {
        return setting.servo_setting[servo]._max;
    }

    static inline void set_min(uint8_t servo, uint16_t _min)
    {
        setting.servo_setting[servo]._min = constrain(_min, 620, 1520);
    }

    static inline void set_max(uint8_t servo, uint16_t _max)
    {
        setting.servo_setting[servo]._max = constrain(_max, 1520, 2420);
    }

    static inline void set_mixing(bool enable)
    {
        setting.mixing = enable;
        if (enable) EIMSK |= (1<<INT1);
        else EIMSK &= ~(1<<INT1);
    }
    static inline void change_mixing()
    {
        set_mixing(!setting.mixing);
    }
    static inline bool get_mixing()
    {
        return setting.mixing;
    }

    static inline void set_radio_type(RADIO_TYPE type)
    {
        setting.radio_type = type;
    }
    static inline void change_radio_type()
    {
        set_radio_type((RADIO_TYPE)(!setting.radio_type));
    }
    static inline RADIO_TYPE get_radio_type()
    {
        return setting.radio_type;
    }

    static void write_servo(uint8_t servo, int16_t angle_10);
    static inline void write_channel_pwm(uint8_t channel, uint16_t micro)
    {
        input[channel] = micro;
    }
    static inline uint16_t get_channel_pwm(uint8_t channel)
    {
        return output[channel];
    }
    static void transfer();


    static void load_setting();
    static void save_setting();

    //void reset_setting();
public:
    static ppm_setting_t setting;

    static uint16_t input[8];
    static uint16_t output[8];
    static uint16_t servo_out[3];
    static bool ppm_in;
private:
    static const int16_t TRIM_MAX;
    static const int16_t TRIM_MIN;
//    static const int16_t TRIM_
};



//extern PPM ppm;

#endif
